package com.briup.pai.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.briup.pai.common.constant.ModelConstant;
import com.briup.pai.common.enums.TrainingStatusEnum;
import com.briup.pai.entity.po.Model;
import com.briup.pai.entity.vo.IndexVO;
import com.briup.pai.entity.vo.ModelChartVO;
import com.briup.pai.entity.vo.ModelCountVO;
import com.briup.pai.service.IIndexService;
import com.briup.pai.service.IModelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Service
public class IndexServiceImpl implements IIndexService {

    @Autowired
    private IModelService modelService;

    @Override
    public IndexVO getModelChartData() {
        IndexVO indexVO = new IndexVO();
        // 封装模型数量
        List<ModelCountVO> modelCountVOS = new ArrayList<>();
        // 统计模型总数（5，数量）
        modelCountVOS.add(new ModelCountVO(ModelConstant.MODEL_TOTAL_COUNT_INDEX,modelService.count()));
        // 根据枚举的值来统计除了错误状态下，各个状态的模型数量
        modelCountVOS.addAll(Arrays.stream(TrainingStatusEnum.values())
                .filter(trainingStatusEnum ->
                        ObjectUtil.notEqual(trainingStatusEnum.getStatus(), TrainingStatusEnum.ERROR.getStatus()))
                .map(trainingStatusEnum ->
                new ModelCountVO(trainingStatusEnum.getStatus(), getModelCount(trainingStatusEnum.getStatus()))).toList());
        indexVO.setModelCounts(modelCountVOS);
        // 封装本周中每一天的模型训练数据

        // 遍历出七天的集合，每天查一下
        indexVO.setModelCharts(getThisWeekDates().stream().map(this::getEverydayModelTrainingData).toList());
        return indexVO;
    }

    // ============ 定义方法 ==========

    /**
     * 根据训练状态统计模型数量
     * @param trainingStatus 训练状态
     * @return 当前训练状态的模型有几个
     */
    private long getModelCount(Integer trainingStatus){
        LambdaQueryWrapper<Model> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Model::getTrainingStatus,trainingStatus);
        return modelService.count(lqw);
    }

    /**
     * 获取本周的Date列表
     * @return 本周的Date列表
     */
    public List<Date> getThisWeekDates() {
        // 获取周一的日期
        Date monday = DateUtil.beginOfWeek(new Date());
        List<Date> list = new ArrayList<>();
        for(int i=0;i<7;i++){
            // 每次让周一向后偏移一天，得到的date装到数组里
            list.add(DateUtil.offsetDay(monday,i));
        }
        return list;
    }

    /**
     * 根据date获取当前天的训练数据（初始化训练+优化训练）
     * @param date java.util.Date
     * @return 用来做柱状图展示本周内所有的训练量
     */
    private ModelChartVO getEverydayModelTrainingData(Date date) {
        // 准备返回值
        ModelChartVO modelChartVO = new ModelChartVO();
        // 查询这一天的初始化训练的模型数量（查询模型版本号为1的模型数量）
        LambdaQueryWrapper<Model> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Model::getLastModelVersion,1)
                        .between(Model::getCreateTime,DateUtil.beginOfDay(date),DateUtil.endOfDay(date));
        modelChartVO.setInitCount(modelService.count(lqw));
        // 查询这一天的优化训练的模型数量，版本号不为1的
        lqw.clear();
        lqw.ne(Model::getLastModelVersion,1).between(Model::getCreateTime,DateUtil.beginOfDay(date),DateUtil.endOfDay(date));
        modelChartVO.setOptimizeCount(modelService.count(lqw));
        return modelChartVO;
    }
}